package cc.shacocloud.mirage.bean.exception;

import cc.shacocloud.mirage.bean.meta.BeanKey;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Objects;

/**
 * 对象创建时的循环依赖异常
 *
 * @author 思追(shaco)
 */
public class BeanCircularDependencyException extends BeanException {
    
    @Getter
    @NotNull
    private final Collection<BeanKey> beans;
    @Setter
    @Getter
    @Nullable
    private BeanKey beanKey;
    
    public BeanCircularDependencyException(@Nullable BeanKey beanKey,
                                           @NotNull Collection<BeanKey> beans) {
        this.beanKey = beanKey;
        this.beans = beans;
    }
    
    public BeanCircularDependencyException(@NotNull Collection<BeanKey> beans) {
        this.beans = beans;
    }
    
    public BeanCircularDependencyException(String message,
                                           @Nullable BeanKey beanKey,
                                           @NotNull Collection<BeanKey> beans) {
        super(message);
        this.beanKey = beanKey;
        this.beans = beans;
    }
    
    public BeanCircularDependencyException(String message,
                                           @NotNull Collection<BeanKey> beans) {
        super(message);
        this.beans = beans;
    }
    
    @Override
    public String getMessage() {
        String message = super.getMessage();
        if (Objects.nonNull(message)) return message;
        
        StringBuilder builder = new StringBuilder();
        
        builder.append("创建对象")
                .append(Objects.nonNull(beanKey) ? " " + beanKey + " " : "")
                .append("出现循环依赖问题，依赖结构如下：\n");
        
        int size = beans.size();
        
        int i = 1;
        for (BeanKey bean : beans) {
            builder.append("\t").append(bean.getBeanClass());
            
            if (i < size) {
                builder.append("\n\t\t ↓");
            }
            i++;
        }
        
        return builder.toString();
    }
}
